<template>
	<view id="questionnaire-investigation">
		<video :style="fileObj.videoStyle" :src="fileObj.videoUrl" @fullscreenclick="fullscreenclick"></video>
		<view>{{fileObj.videoName||"请选择上传视频"}}</view>
		<button @click="uploadVideo">上传视频</button>
		<image :style="fileObj.imageStyle" :src="fileObj.imageUrl" mode="aspectFill"></image>
		<view>{{fileObj.imageName||"请选择上传图片"}}</view>
		<button @click="uploadImage">上传图片</button>
	</view>
</template>
<script setup>
	import {
		ref,
		reactive
	} from "vue";
	import {
		onLoad,
		onReady
	} from '@dcloudio/uni-app'

	import SparkMD5 from 'spark-md5'; // 引入md5
	const spark = new SparkMD5(); // 实例化
	// console.log(spark);
	const fullscreenclick=(e)=>{
		console.log(e);
	}

	const fileObj = reactive({
		videoStyle: "display: block;",
		videoUrl: "http://testfile.tcwang.cc/2024011219051115OWV82715.mp4",
		videoName: "",
		imageStyle: "display: none;",
		imageUrl: "",
		imageName: "",
	})

	/**
	 * 视频分片上传
	 * 分析：
	 * 1、将一个几百M的视频分为每 2M 的小块，依次传给后端
	 * 1 MB = 1024 KB
	 * 1 KB = 1024 B/字节
	 * 2M = 1024 * 1024 * 2 = 2097152
	 * 
	 * 注意视频的 "File" 对象和 "Blob" 对象保存了文件的基本信息，所以分片很快
	 * File：size；type；name；
	 * Blob：size；type
	 * 
	 * 利用 "FileReader" 读取数据
	 * 
	 * 2、上传文件遇到断网或者暂停之类的，下次上传不用把上传过的文件重新上传可使用hash值
	 * 
	 * hash   md5    （三方库：spark md5）
	 *          单向，不可逆
	 * 任何数据——————————————>hash值（固定长度的字符串）
	 * 
	 * 不可一次获取文件的hash，视频很大，内存会过载（内存溢出）
	 * 可用 "增量算法"——就是拿一块数计算完成不要了，将结果保存着，接着计算下一个文件，将结果与上一个结果加起来，以此反复
	 * 
	 * 3、hash运算过程会根据文件大小可长可短，所以不会放到主线程
	 * 	可以利用 "web worker" 单独开一个线程来处理hash运算过程，避免浏览器卡死
	 * */

	/**
	 * 分片函数：一个简单的数学运算
	 * file：需要分片的文件
	 * chunksSize：分片体积
	 * fileType：文件类型
	 */
	const createChunks = (file, chunksSize, fileType) => {
		const result = [];
		for (let i = 0; i < file.size; i += chunksSize) {
			// 使用File对象的slice方法提取图像的部分数据（例如,前2M）
			result.push(file.slice(i, i + chunksSize, fileType))
		}
		return result;
	}

	/**
	 * 获取文件的hash（增量算法）
	 * chunks：分片后的数组
	 */
	const getHashValue = (chunks = []) => {
		// 因为计算比较慢,弄一个异步
		return new Promise(resolve => {
			// 递归函数：这个分块读完再读下一个分块，将结果合在一起
			const _read = (i) => {
				// 递归终止条件：全部分片读取完成
				if (i >= chunks.length) {
					resolve(spark.end()); // 得到hash返回出去
					return; // 读取完成
				}
				const blod = chunks[i]; // 拿到当前分块
				const reader = new FileReader(); // 实例化文件读取函数
				// 读取过程是异步的
				reader.onload = e => {
					// 当读完之后拿到读取到的字节数组
					const bytes = e.target.result;
					// 将字节数组使用增量hash进行计算
					spark.append(bytes); // 把一组字节加到hash运算中，完成增量计算
					_read(i + 1); // 下一分片
				}
				fileReader.onerror = () => {
					reject('读取失败')
				}
				reader.readAsArrayBuffer(blod); // 读字节数数组
			}
			_read(0)
		})

	}

	const uploadChunks = (chunks) => {
		// 循环请求
		chunks.forEach((chunk, index) => {
			// console.log(chunk);
			// const reader = new FileReader(); // 实例化文件读取函数
			// // 读取过程是异步的
			// reader.onload = e => {
			// 	// 当读完之后拿到读取到的字节数组
			// 	const bytes = e.target.result;
			// 	console.log(bytes);				
			// }
			// reader.readAsArrayBuffer(chunk); // 读字节数数组

			const formData = new FormData(); // 
			formData.append('file', chunk)

			console.log(formData);
			// 上传方法
			// uni.uploadFile({
			// 	url: proxy.$baseUrl + '/system/file/uploadFile', // 仅为示例，非真实的接口地址
			// 	filePath: url,
			// 	header: {
			// 		"content-type": "application/x-www-form-urlencoded",
			// 		"Source": "3",
			// 		"from": "tcHouseRing",
			// 		"FunRing-Token": sto.token || uni.getStorageSync('token') || null
			// 	},
			// 	formData: {
			// 		type: 3, //1 图片 2.文件 3. 视频
			// 		needNoWatermark: false
			// 	},
			// 	name: 'file',
			// 	success: (res) => {
			// 		console.log(res, '成功了');
			// 	},
			// 	fail(err) {
			// 		console.log(err, '出错了');
			// 	}
			// });
		});
	}

	const uploadVideo = () => {
		console.log("上传视频");
		uni.chooseVideo({
			sourceType: ['camera', 'album'],
			compressed: false,
			success: async (res) => {
				// console.log(res);
				// fileObj.videoUrl = res.tempFilePath;
				fileObj.videoStyle = "display: block;";
				// let file = res.tempFile; // 获取File对象
				// fileObj.videoName = file.name;
				// if (!file) return;
				// // let chunks = createChunks(file, 200 * 1024); // 得到分片数组(200KB)
				// let chunks = createChunks(file, 2 * 1024 * 1024); // 得到分片数组
				// console.log(chunks);
				// const result = await getHashValue(chunks); // 计算hash值
				// console.log(result);
			}
		});
	}
	const uploadImage = () => {
		console.log("图片");
		uni.chooseImage({
			count: 1, //默认9
			sizeType: ['original'], //可以指定是原图还是压缩图，默认二者都有
			sourceType: ['camera', 'album'],
			success: async (res) => {
				console.log(res);
				// fileObj.imageUrl = res.tempFilePaths[0];
				// fileObj.imageStyle = "display: block;";
				let file = res.tempFiles[0]; // 获取File对象
				fileObj.imageName = file.name;
				if (!file) return;
				// 得到分片数组(200KB)
				let chunks = createChunks(file, 200 * 1024, file.type);
				// let chunks = createChunks(file, 2 * 1024 * 1024); // 得到分片数组
				// console.log(chunks);
				// 计算hash值	
				// const result = await getHashValue(chunks);			
				// console.log(result);
				// 文件上传
				uploadChunks(chunks)
			}
		});
	}
</script>

<style lang="scss" scoped>
	* {
		box-sizing: border-box;
	}
</style>